﻿using System;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using JTLeigh.Tools.Development.CopySourceAsHtml.Properties;

namespace JTLeigh.Tools.Development.CopySourceAsHtml.UnitTests.Properties
{

    /// <summary>
    /// Unit tests for the <see cref="Settings"/> class.
    /// </summary>
    [TestClass]
    public class SettingsFixture
    {
        #region Methods

        #region Serialization

        /// <summary>
        /// Ensures <see cref="Settings"/> can be serialized to and deserialized from XML with no 
        /// loss of data.
        /// </summary>
        [TestMethod]
        public void TestSerializeDeserialize()
        {
            XmlSerializer serializer;
            MemoryStream stream;
            PropertyInfo[] properties;
            Settings originalSettings;
            Settings copiedSettings;

            serializer = new XmlSerializer(typeof(Settings));
            stream = new MemoryStream();
            properties = typeof(Settings).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

            // NOTE: We're using reflection to ensure none of the settings have their default 
            // value, so we can be sure the values we deserialize are in fact the values we set,
            // not the defaults.
            originalSettings = new Settings();
            foreach (PropertyInfo property in properties)
            {
                if (property.PropertyType.Equals(typeof(String)))
                {
                    property.SetValue(originalSettings, ("Test" + (string)property.GetValue(originalSettings, null) + "Test"), null);
                }
                else if (property.PropertyType.Equals(typeof(int)))
                {
                    property.SetValue(originalSettings, (int)((int)property.GetValue(originalSettings, null) + 1), null);
                }
				else if (property.PropertyType.Equals(typeof(byte)))
				{
					property.SetValue(originalSettings, (byte)((byte)property.GetValue(originalSettings, null) + 1), null);
				}
				else if (property.PropertyType.Equals(typeof(bool)))
				{
					property.SetValue(originalSettings, (!(bool)property.GetValue(originalSettings, null)), null);
				}
				else if (property.PropertyType.Equals(typeof(double)))
				{
					property.SetValue(originalSettings, ((double)property.GetValue(originalSettings, null) + 0.5d), null);
				}
				else
                {
                    Assert.Fail("This test needs to be extended to support property type '{0}'.", property.PropertyType);
                }
            }

            serializer.Serialize(Console.Out, originalSettings);
            serializer.Serialize(stream, originalSettings);
            stream.Position = 0;

            copiedSettings = (Settings)serializer.Deserialize(stream);
            foreach (PropertyInfo property in properties)
            {
                Assert.AreEqual(property.GetValue(originalSettings, null), property.GetValue(copiedSettings, null));
            }
        }

        #endregion // Serialization

        #endregion // Methods
    }

}
